import { Directive, Input } from '@angular/core';
import {
  NG_ASYNC_VALIDATORS,
  AbstractControl,
  ValidationErrors,
  AsyncValidator,
  AsyncValidatorFn,
} from '@angular/forms';
import { Observable, of, timer } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { UserService } from 'src/app/benshuo/services/user.service';
import { MajorService } from 'src/app/benshuo/services/major.service';
/**
 * 异步验证函数，可用于FormGroup 检查组织机构代码唯一性验证
 * 用法：
 *   FormBuilder.group({
 *     code: ['',[同步验证],[asyncRoleNameValidator(this.roleService, id)]]
 *   });
 * @param roleService 权限服务
 */
export function asyncConectionMajorNameValidator(service: MajorService, constructionId?: string): AsyncValidatorFn {
  return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
    // console.log(`trigger validation: ${control.value}`);
    // 如果数据被改变且不为空，则请求后台验证
    if (control.dirty && control.value && control.value !== '') {
      // 为了避免频繁向后台请求，0.5秒后再调用API
      return timer(500).pipe(
        switchMap(() => {
          // console.log(`call validation api: ${control.value}`);
          return service.checkAccountUnique(control.value, constructionId).pipe(
            map(res => {
              return res.data ? null : { nameExists: `${control.value}已经被占用` };
            }),
          );
        }),
      );
    } else {
      return of(null);
    }
  };
}

/**
 * 指令，用于模板驱动的表单
 */
@Directive({
  // tslint:disable-next-line: directive-selector
  selector: '[app-async-majorname-validator]',
  providers: [
    {
      provide: NG_ASYNC_VALIDATORS,
      useExisting: AsyncMajorNameValidatorDirective,
      multi: true,
    },
  ],
})
/**
 * 检查专业名称唯一性
 */
export class AsyncMajorNameValidatorDirective implements AsyncValidator {
  @Input()
  userId: string | AbstractControl;

  constructor(private majorService: MajorService) {}

  validate(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
    // 如果是字符串则认为是控件名，否则为控件，取控件的值
    const idControl = typeof this.userId === 'string' ? control.parent.get(this.userId) : this.userId;
    // 如果控件不存在，则认为authorityId就是id值
    const value = idControl ? idControl.value : this.userId;
    return asyncConectionMajorNameValidator(this.majorService, value)(control);
  }
}
